package com.wesley.growth.future;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * CompletableFutureDemo
 *
 * @author WangPanYong
 * @since 2023/01/20 16:05
 */
public class CompletableFutureDemo {

    public static void main(String[] args) throws Exception {
//        get();
        thenApply(args);
    }

    /**
     * get
     * 打断 get 方法立即获得返回括号值。
     *
     * @author WangPanYong
     * @since 2023/02/06 17:52
     **/
    private static void get() throws Exception {
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 533;
        });

        // 注释掉暂停线程，get还没有算完只能返回complete方法设置的444；
        try {
            // 暂停2秒钟线程，异步线程能够计算完成返回get
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 当调用CompletableFuture.get()被阻塞的时候,complete方法就是结束阻塞并get()获取设置的complete里面的值.
        System.out.println(completableFuture.complete(444) + "\t" + completableFuture.get());
    }

    /**
     * 计算结果存在依赖关系，这两个线程串行化，由于依赖关系，当前步骤有异常就叫停，主线程如果结束，默认线程池就会关闭。
     */
    public static void thenApply(String[] args) throws Exception {
        //当一个线程依赖另一个线程时用 thenApply 方法来把这两个线程串行化,
        CompletableFuture.supplyAsync(() -> {
            //暂停几秒钟线程
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("111");
            return 1024;
        }).thenApply(f -> {
            System.out.println("222");
            return f + 1;
        }).thenApply(f -> {
            //int age = 10/0; // 异常情况：那步出错就停在那步。
            System.out.println("333");
            return f + 1;
        }).whenCompleteAsync((v, e) -> {
            System.out.println("*****v: " + v);
        }).exceptionally(e -> {
            e.printStackTrace();
            return null;
        });

        System.out.println("-----主线程结束，END");

        // 主线程不要立刻结束，否则CompletableFuture默认使用的线程池会立刻关闭:
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
